// HeuristicObject.cpp: implementation of the HeuristicObject class.
//
//////////////////////////////////////////////////////////////////////

#include "HeuristicObject.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

HeuristicObject::HeuristicObject()
{
}

HeuristicObject::~HeuristicObject()
{
	if (tilePosForGetH) delete[] tilePosForGetH;
	if (huristicTable) delete[] huristicTable;
}

// Description	    : This function reads the Pattern Data Base from File
void HeuristicObject::Initialize(Parameters *in_parm, GameObject *in_topSpinObj)
{
	parm = in_parm;
	topSpinObj = in_topSpinObj;
	huristicTable = new UCHAR[TABLESIZE];
	tilePosForGetH = new int[PATTERNSIZE];

	if(in_parm->pdb_ptr ==NULL)
		{printf("\nerror loading \n");exit(0);}
	fread(huristicTable,sizeof(UCHAR)*TABLESIZE,1,in_parm->pdb_ptr);

	for (int i = 0; i < SIZE; i++)
		arrPatternLocation[i] = -1;
	
	AnalyzePattern(in_parm->getPDBFileName());


}

void HeuristicObject::Reset()
{

}



int HeuristicObject::GetHuristicRegular(int state[SIZE])
{
	I64 hashVal,entry;
	int tilesPos[PATTERNSIZE];
	int val;

	ConverteTilesToTilesPos(state, tilesPos);
	hashVal=hash(tilesPos);
	

	if (!SHRINKDATABASE)
	{
		val = huristicTable[hashVal];
		return val;

	}
	else
	{
		entry =  hashVal>>1;
		val = huristicTable[entry];
		if ((entry<<1)==hashVal)
			val = val>>4;
		else
			val =  val&15;
//		if (val>13)
//			printf("Faile Val = %d",val);

		return val;
	}
}


void HeuristicObject::ConverteTilesToTilesPos(int pop[SIZE], int tilepos[PATTERNSIZE])
{
	for (int i=0;i<SIZE;i++)
	{
		int tile = pop[i];
		if (arrPatternLocation[tile]!=-1)
			tilepos[arrPatternLocation[tile]] = i;
	}
}

// Function name	: hash
// Description	    : Convarte tiles into hash Number
// Return type		: I64 
// Argument         : int *in_tiles
I64  HeuristicObject::hash(int tiles[PATTERNSIZE])
{
//	PrintTiles(in_tiles);
	int i,digit,j;
	I64 hashval = 0;
	for (i = 0; i < PATTERNSIZE ; i++)                         /* for each remaining position in permutation */
    {digit = tiles[i] ;                                  /* initially digit is value in permutation */
      for (j = 0; j < i; j++)                           /* for each previous element in permutation */
       if (tiles[j] < tiles[i]) digit--; /* previous position contains smaller value, decrement digit*/
         hashval = hashval * (SIZE - i) + digit;}              /* multiply digit by appropriate factor */
	return hashval;
}




int HeuristicObject::eval(int state[SIZE])
{
	int myh;
	myh = 0;
	if (MAKE_ITERATIVE_DEP)
		return 0;
	myh = GetHuristicRegular(state);
	return myh;
}





void HeuristicObject::AnalysePDB()
{
	if (huristicTable == NULL)
	{
		printf("Heuristic Table wasn't initialize yet\n");
		return;
	}

	UCHAR val,curVal,maxVal;I64 maxContinuity,curContinuity,entry;
	double acc=0;
	curVal = 0;
	maxVal = 0;
	for (I64 i=0;i<TABLESIZE;i++)
	{
		if (!SHRINKDATABASE)
		{
			val = huristicTable[i];
		}
		else
		{
			entry =  i>>1;
			val = huristicTable[entry];
			if ((entry<<1)==i)
				val = val>>4;
			else
				val =  val&15;
	//		if (val>13)
	//			printf("Faile Val = %d",val);
		}
		if (val == curVal)
		{
			curContinuity++;
		}
		else
		{
			if (maxContinuity<curContinuity)
				maxContinuity=curContinuity;
			curContinuity = 0;
			curVal = val;
		}
		maxVal = MAX(maxVal,val);
		acc+=val;
	}
	printf("maxContinuity = %I64d\n",maxContinuity);
	printf("Max Value %d\n",(int)maxVal);
	printf("Total values = %.3f\n",acc);
	printf("Table size = %ld\n",TABLESIZE);
	long l = TABLESIZE;
	printf("Average values %.3f\n",acc/(double)l);
}


void HeuristicObject::AnalyzePattern(char *patternFileName)
{
	int number1,i;
	char *token;
	char name[100];
	int PatArray[PATTERNSIZE];
	strcpy(name,patternFileName);
	token = strtok(name,"_");
	token = strtok(NULL,"_");
	int acc =0;
	while(token)
	{
		PatArray[acc] = atoi(token);
		token = strtok(NULL,"_");
		acc++;
	}

	if (acc!=PATTERNSIZE)
	{
		printf("Faile in get_input_parameters \n");
		printf("PATTERNSIZE = %d ,but read %d tiles from file %s\n",PATTERNSIZE,acc,patternFileName);
		exit(0);
	}



	acc =0;
	for (i=0;i<SIZE;i++)
		arrPatternLocation[i] = -1;
	//0 - the first symbol get -1     Note Symbole 0 belong to pattern automaticly
	//The second symbol get 0 
	//The 3rd get 1...

	for (i=0;i<PATTERNSIZE;i++)
	{
		number1 = PatArray[i];
		arrPatternLocation[number1] = acc;
		acc++;
	}
}

